package com.hk.core.jdbc;

import com.hk.commons.query.AndOr;
import com.hk.commons.query.Order;
import com.hk.commons.query.QueryModel;
import com.hk.commons.util.CollectionUtils;
import com.hk.core.jdbc.query.CompositeCondition;
import com.hk.core.jdbc.query.Condition;
import com.hk.core.jdbc.query.Parametric;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.function.Supplier;

/**
 * @author kevin
 * @date 2018-09-19 10:48
 */
@Data
@Accessors(chain = true)
@NoArgsConstructor
public final class SelectArguments {

    /**
     * 去重
     */
    private boolean distinct = false;

    /**
     * 查询字段
     */
    private Collection<String> fields;

    /**
     * 要查询的表名
     */
    private String from;

    /**
     * 条件 where conditions
     */
    private CompositeCondition conditions = new CompositeCondition();
    /**
     * 分组
     */
    private Collection<String> groupBy = new LinkedHashSet<>();

    /**
     * Select count(*) || select count(id)
     * 默认所有主键字段为 id
     */
    private String countField = "id";

    /**
     * 排序
     */
    private List<Order> orders = new ArrayList<>();

    /**
     * 分页参数
     */
    private int startRowIndex;

    /**
     * 分页参数
     */
    private int pageSize;

    private Parametric parametric;

    public static SelectArguments newSelectArguments(QueryModel<?> query) {
        return new SelectArguments()
                .setOrders(query.getOrders())
                .setStartRowIndex(query.getStartRowIndex())
                .setPageSize(query.getPageSize());
    }

    public SelectArguments fields(String... fields) {
        if (null == this.fields) {
            this.fields = new LinkedHashSet<>();
        }
        CollectionUtils.addAllNotNull(this.fields, fields);
        return this;
    }

    public SelectArguments groupBys(String... groupBy) {
        CollectionUtils.addAllNotNull(this.groupBy, groupBy);
        return this;
    }

    public SelectArguments addOrder(Order order) {
        this.orders.add(order);
        return this;
    }

    public SelectArguments addCondition(boolean matcher, Supplier<Condition> supplier) {
        if (matcher) {
            this.conditions.addCondition(supplier.get());
        }
        return this;
    }

    public SelectArguments addCondition(Condition condition) {
        this.conditions.addCondition(condition);
        return this;
    }

    public SelectArguments addConditions(Condition... conditions) {
        this.conditions.addConditions(conditions);
        return this;
    }

    public SelectArguments addConditions(Collection<? extends Condition> conditions) {
        this.conditions.addConditions(conditions);
        return this;
    }

    public SelectArguments removeCondition(Condition condition) {
        this.conditions.removeCondition(condition);
        return this;
    }

    public SelectArguments clearConditions() {
        this.conditions.clearConditions();
        return this;
    }

    public SelectArguments removeCondition(int index) {
        this.conditions.removeCondition(index);
        return this;
    }

    public SelectArguments andOr(AndOr andOr) {
        this.conditions.setAndOr(andOr);
        return this;
    }
}
